package com.cmc.cloud.cmclink.doc.util;

import com.cmc.cloud.cmclink.doc.util.sepcial.CommonUtil;
import org.redisson.api.*;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author huzheng
 */
@Component
public class RedisUtils implements ApplicationContextAware {


    private static final String REDIS_KEY_PREFIX = "doc:";
    private RedissonClient redissonClient;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        redissonClient = applicationContext.getBean(RedissonClient.class);
    }

    public boolean checKeyExist(String key) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        return bucket.isExists();
    }

    /**
     * 按照分钟设置过期的key
     *
     * @param key
     * @param value
     * @param minute
     */
    public void setStringTimeOutByMinute(String key, String value, long minute) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        bucket.set(value, minute, TimeUnit.MINUTES);
    }

    /**
     * 操作 String
     */
    public void setString(String key, String value, long days) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        bucket.set(value, days, TimeUnit.DAYS);
    }

    public Long getAtomicLong(String key) {
        RAtomicLong counter = redissonClient.getAtomicLong(REDIS_KEY_PREFIX + key);
        if (!counter.isExists()) {
            counter.set(0);
            long ttlMillis = CommonUtil.calculateMillisToEndOfYear();
            counter.expire(ttlMillis, TimeUnit.MILLISECONDS);
        }
        return counter.incrementAndGet();
    }

    /**
     * 操作 String 永久
     */
    public void setString(String key, String value) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        bucket.set(value);
    }

    /**
     * 删除 String
     */
    public void deleteString(String key) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        bucket.delete();
    }

    /**
     * 删除 String
     */
    public Object getAndDeleteString(String key) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        return bucket.getAndDelete();
    }

    public void setString(String key, String value, Long time, TimeUnit timeUnit) {
        RBucket<Object> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        bucket.set(value, time, timeUnit);
    }

    public String getString(String key) {
        RBucket<String> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        return bucket.get();
    }

    public String getKeys(String key) {
        RBucket<String> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        return bucket.get();
    }

    public List<String> getStringList(String key) {
        RKeys keys = redissonClient.getKeys();
        Iterable<String> keysByPattern = keys.getKeysByPattern("*" + key + "*");
        List<String> result = new ArrayList<>();
        for (String s : keysByPattern) {
            result.add(s);
        }
        return result;
    }

    public boolean evalScript(String luaScript, String key, String value) {
        RScript script = redissonClient.getScript();
        return script.eval(RScript.Mode.READ_WRITE, luaScript, RScript.ReturnType.BOOLEAN, Collections.singletonList(REDIS_KEY_PREFIX + key), value);
    }

    public Boolean remove(String key) {
        RBucket<String> bucket = redissonClient.getBucket(REDIS_KEY_PREFIX + key);
        return bucket.delete();
    }

    /**
     * <p>获取自定义项目前缀 Hash结构指定node key 值</p>
     *
     * @param key       缓存的key名
     * @param hashKey   hashKey
     * @param prefixKey 缓存的key名前缀 例如 项目名
     * @return Map<String, T>
     */
    public String hashGet(String key, String hashKey, String prefixKey) {

        return this.getMap(prefixKey + ":" + key, hashKey);
    }

    /**
     * <p>获取hash结构</p>
     *
     * @param key     缓存key名
     * @param hashKey hashKey
     * @return T
     */
    private String getMap(String key, String hashKey) {
        RMap<String, String> map = redissonClient.getMap(key);
        return map.get(hashKey);
    }


    /**
     * map.put
     *
     * @param key
     * @param mapKey
     * @param mapValue
     */
    public void mapPut(String key, String mapKey, String mapValue) {
        RMap<String, String> rMap = redissonClient.getMap(key);
        rMap.put(mapKey, mapValue);

    }

    /**
     * map.put
     *
     * @param key
     * @param mapKey
     * @param mapValue
     */
    public void mapPut(String key, String mapKey, Integer mapValue) {
        RMap<String, Integer> rMap = redissonClient.getMap(key);
        rMap.put(mapKey, mapValue);

    }
}
